﻿using System;
using System.Collections.Generic;
using System.IO;
using Needle.Bus.Engine.Schedulers;
using Needle.Bus.Messages.Management;

namespace Needle.Bus.Engine.Factories
{
    public class EngineFactory : IFactory<Engine>
    {

        BusConfigurationFactory _cfgFactory;

        public EngineFactory(string configurationFilePath)
        {
            if (String.IsNullOrEmpty(configurationFilePath))
                throw new ArgumentException("configurationFilePath is null or empty.", "configurationFilePath");
            
            var cfgFile = new FileInfo(configurationFilePath);
            if (!cfgFile.Exists)
                throw new FileNotFoundException("configuration file not found", cfgFile.FullName);
            using (var cfgStream = cfgFile.OpenRead())
            {
                _cfgFactory = new BusConfigurationFactory(cfgStream);
            }
        }
        public Engine Create(string id)
        {
            var busConfig = _cfgFactory.Create(id);
            var filterFactory = new StageFilterFactory(busConfig);
            var handlerFactory = new MessageHandlerFactory(busConfig);
            var perfCounterFactory = new PerfCounterFactory(busConfig);
            var stageFactory = new StageFactory(
                                   busConfig, 
                                   filterFactory, 
                                   handlerFactory, 
                                   perfCounterFactory);

            IScheduler scheduler = new Scheduler(id);
            Engine engine = new Engine(id, stageFactory, scheduler);

            var forcedStartStages = new List<string>();
            foreach (var stage in busConfig.Stages)
                if (!stage.StartOnDemand)
                    forcedStartStages.Add(stage.Id);

            if (forcedStartStages.Count > 0)
            {
                var stageController = engine.GetStage(BusAddress.StageController);
                forcedStartStages.ForEach(x => stageController.Buffer.Enqueue(new StartStageMessage { StageId = x }));
            }

            return engine;
        }

        public IList<Engine> CreateAll()
        {
            throw new NotSupportedException();
        }
    }
}
